﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace _3Dsoundor2Dgraphor.Sound
{
	class SoundSystem : SoundBase
	{

		public SoundSystem ()
		{
			uint version = 0;

			/*
				Create a System object and initialize.
			*/
			result = FMOD.Factory.System_Create(ref system);
			ERRCHECK(result);

			result = system.getVersion(ref version);
			ERRCHECK(result);
			if (version < FMOD.VERSION.number)
			{
				MessageBox.Show("Error!  You are using an old version of FMOD " + version.ToString("X") + ".  This program requires " + FMOD.VERSION.number.ToString("X") + ".");
				Application.Exit();
			}

			FMOD.CAPS caps = FMOD.CAPS.NONE;
			FMOD.SPEAKERMODE speakermode = FMOD.SPEAKERMODE.STEREO;

			int minfrequency = 0, maxfrequency = 0;
			StringBuilder name = new StringBuilder(128);

			result = system.getDriverCaps(0, ref caps, ref minfrequency, ref maxfrequency, ref speakermode);
			ERRCHECK(result);

			result = system.setSpeakerMode(speakermode);                             /* Set the user selected speaker mode. */
			ERRCHECK(result);

			if ((caps & FMOD.CAPS.HARDWARE_EMULATED) == FMOD.CAPS.HARDWARE_EMULATED) /* The user has the 'Acceleration' slider set to off!  This is really bad for latency!. */
			{                                                                        /* You might want to warn the user about this. */
				result = system.setDSPBufferSize(1024, 10);	                     /* At 48khz, the latency between issuing an fmod command and hearing it will now be about 213ms. */
				ERRCHECK(result);
			}

			FMOD.GUID guid = new FMOD.GUID();

			result = system.getDriverInfo(0, name, 256, ref guid);
			ERRCHECK(result);

			result = system.init(32, FMOD.INITFLAGS.NORMAL, (IntPtr)null);
			if (result == FMOD.RESULT.ERR_OUTPUT_CREATEBUFFER)
			{
				result = system.setSpeakerMode(FMOD.SPEAKERMODE.STEREO);             /* Ok, the speaker mode selected isn't supported by this soundcard.  Switch it back to stereo... */
				ERRCHECK(result);

				result = system.init(32, FMOD.INITFLAGS.NORMAL, (IntPtr)null);        /* Replace with whatever channel count and flags you use! */
				ERRCHECK(result);
			}

			set3DsystemDistance(DISTANCEFACTOR);
			/*
				Load some sounds
			*/
			//result = system.createSound("c:\\sounds\\drumloop.wav", (FMOD.MODE.HARDWARE | FMOD.MODE._3D), ref sound1);
			//ERRCHECK(result);
			//result = sound1.set3DMinMaxDistance(2.0f * DISTANCEFACTOR, 10000.0f * DISTANCEFACTOR);
			//ERRCHECK(result);
			//result = sound1.setMode(FMOD.MODE.LOOP_NORMAL);
			//ERRCHECK(result);

			//result = system.createSound("c:\\sounds\\jaguar.wav", (FMOD.MODE.HARDWARE | FMOD.MODE._3D), ref sound2);
			//ERRCHECK(result);
			//result = sound2.set3DMinMaxDistance(2.0f * DISTANCEFACTOR, 10000.0f * DISTANCEFACTOR);
			//ERRCHECK(result);
			//result = sound2.setMode(FMOD.MODE.LOOP_NORMAL);
			//ERRCHECK(result);

			//result = system.createSound("c:\\sounds\\swish.wav", (FMOD.MODE.HARDWARE | FMOD.MODE._2D), ref sound3);
			//ERRCHECK(result);

			/*
				Play sounds at certain positions
			*/
			//{
			//    FMOD.VECTOR pos1 = new FMOD.VECTOR();
			//    pos1.x = -10.0f * DISTANCEFACTOR; pos1.y = -0.0f; pos1.z = 0.0f;

			//    FMOD.VECTOR vel1 = new FMOD.VECTOR();
			//    vel1.x = 0.0f; vel1.y = 0.0f; vel1.z = 0.0f;

			//    result = system.playSound(FMOD.CHANNELINDEX.FREE, sound1, true, ref channel1);
			//    ERRCHECK(result);
			//    result = channel1.set3DAttributes(ref pos1, ref vel1);
			//    ERRCHECK(result);
			//    result = channel1.setPaused(false);
			//    ERRCHECK(result);
			//}

			//{
			//    FMOD.VECTOR pos2 = new FMOD.VECTOR();
			//    pos2.x = 15.0f * DISTANCEFACTOR; pos2.y = -0.0f; pos2.z = -0.0f;

			//    FMOD.VECTOR vel2 = new FMOD.VECTOR();
			//    vel2.x = 0.0f; vel2.y = 0.0f; vel2.z = 0.0f;

			//    result = system.playSound(FMOD.CHANNELINDEX.FREE, sound2, true, ref channel2);
			//    ERRCHECK(result);
			//    result = channel2.set3DAttributes(ref pos2, ref vel2);
			//    ERRCHECK(result);
			//    result = channel2.setPaused(false);
			//    ERRCHECK(result);
			//}

			//lastpos.x = 0.0f;
			//lastpos.y = 0.0f;
			//lastpos.z = 0.0f;

			//listenerpos.x = 0.0f;
			//listenerpos.y = 0.0f;
			//listenerpos.z = -1.0f * DISTANCEFACTOR;
		}

		public void set3DsystemDistance (float defaultDistance)
		{
			result = system.set3DSettings(1.0f, defaultDistance, 1.0f);
			ERRCHECK(result);
		}
	}
}
